package com.xbongbong.saas.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.FormDataValidateDataHelp;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.service.PaasFormExplainService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.pro.enums.errorcodes.ProductErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.product.pojo.dto.ProductStockInfoSaveDTO;
import com.xbongbong.pro.productbaseinfo.pojo.dto.ProductBaseInfoDeleteBatchDTO;
import com.xbongbong.pro.productbaseinfo.pojo.dto.ProductBaseInfoListDTO;
import com.xbongbong.pro.productbaseinfo.pojo.vo.ProductBaseInfoDeleteBatchVO;
import com.xbongbong.pro.productbaseinfo.pojo.vo.ProductBaseInfoListVO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.domain.entity.InstockProductEntity;
import com.xbongbong.saas.domain.entity.OutstockProductEntity;
import com.xbongbong.saas.domain.entity.ProductBaseInfoEntity;
import com.xbongbong.saas.domain.entity.ProductStockInfoEntity;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.RelativeProductEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.ProductBaseInfoModel;
import com.xbongbong.saas.model.ProductStockInfoModel;
import com.xbongbong.saas.service.ProductBaseInfoService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 产品库存信息接口实现类
 *
 * @author chaoxiong.lei
 * @date 2019/2/26 20:51
 */
@Service("productBaseInfoService")
public class ProductBaseInfoServiceImpl implements ProductBaseInfoService {

    private static final Logger LOG = LoggerFactory.getLogger(ProductBaseInfoServiceImpl.class);

    @Resource
    private ProductBaseInfoModel productBaseInfoModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PaasFormExplainService paasFormExplainService;
    @Resource
    private ProductStockInfoModel productStockInfoModel;
    @Resource
    private FormDataValidateDataHelp formDataValidateDataHelp;

    @Override
    public void saveProductBaseInfo(ProductStockInfoSaveDTO productStockInfoSaveDTO) throws XbbException {
        String corpid = productStockInfoSaveDTO.getCorpid();
        JSONObject productObj = productStockInfoSaveDTO.getProductObj();
        Long refId = productStockInfoSaveDTO.getRefId();
        Integer refType = productStockInfoSaveDTO.getRefType();
        String productName = productStockInfoSaveDTO.getProductName();
        String operateType = productStockInfoSaveDTO.getOperateType();
        Integer isProductStockInfo = productStockInfoSaveDTO.getIsProductStockInfo();
        // 获取库存产品的解释
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.STOCK_PRODUCT.getCode(), corpid);
        if (null == paasFormExplainEntity) {
            throw new XbbException(ProductErrorCodeEnum.API_ERROR_205035);
        }
        List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);

        // 前端传入的数据
        String batch = productObj.getString("batch");
        Long produceDate = DateTimeUtil.getInt(productObj.getString("produceDate"), DateUtil.SDFDate);
        String guaranteePeriodStr = productObj.getString("guaranteePeriod");
        String memo = Objects.toString(productObj.getString("memo"), "").trim();
        // 库存模板自定义字段
        String redundantData = productObj.getString("redundantData") == null ? "{}" : productObj.getString("redundantData");
        // 备注去掉emoji表情
        memo = StringUtil.filterEmoji(memo);

        // ----------------备注校验------------------
        Boolean memoRequired = paasFormExplainService.checkRequiredBySaasAttr(explainList, RelativeProductEnum.MEMO.getSaasAttr());
        if (memoRequired && StringUtil.isEmpty(memo)) {
            throw new XbbException(ProductErrorCodeEnum.API_ERROR_205029, ProductErrorCodeEnum.API_ERROR_205029.getMsg() + ":" + productName);
        }
        if (memo.length() > BasicConstant.PRODUCT_MEMO_MAX_LENGTH) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100056, SystemErrorCodeEnum.API_ERROR_100056.getMsg() + ":" + productName);
        }

        // ----------------保质期校验------------------
        Boolean guaranteeRequired = paasFormExplainService.checkRequiredBySaasAttr(explainList, RelativeProductEnum.GUARANTEE_PERIOD.getSaasAttr());
        if (guaranteeRequired && StringUtil.isEmpty(guaranteePeriodStr)) {
            throw new XbbException(ProductErrorCodeEnum.API_ERROR_205032, ProductErrorCodeEnum.API_ERROR_205032.getMsg() + ":" + productName);
        }
        Long guaranteePeriod = null;
        if (!StringUtil.isEmpty(guaranteePeriodStr)) {
            if (!StringUtil.isDigital(guaranteePeriodStr)) {
                throw new XbbException(ProductErrorCodeEnum.API_ERROR_205019);
            }
            Long guaranteePeriodLong;
            try {
                guaranteePeriodLong = Long.parseLong(guaranteePeriodStr);
            } catch (NumberFormatException e) {
                throw new XbbException(ProductErrorCodeEnum.API_ERROR_205019);
            }
            if (guaranteePeriodLong < 0L) {
                throw new XbbException(ProductErrorCodeEnum.API_ERROR_205019);
            }
            if (guaranteePeriodLong > 20000L) {
                throw new XbbException(ProductErrorCodeEnum.API_ERROR_205019);
            }
            guaranteePeriod = Integer.valueOf(guaranteePeriodStr) * 86400L;
        }

        // ----------------生产日期校验------------------
        Boolean produceDateRequired = paasFormExplainService.checkRequiredBySaasAttr(explainList, RelativeProductEnum.PRODUCE_DATE.getSaasAttr());
        if (produceDateRequired && (produceDate == null || produceDate == 0)) {
            throw new XbbException(ProductErrorCodeEnum.API_ERROR_205031, ProductErrorCodeEnum.API_ERROR_205031.getMsg() + ":" + productName);
        }

        // ----------------批次校验------------------
        Boolean batchRequired = paasFormExplainService.checkRequiredBySaasAttr(explainList, RelativeProductEnum.BATCH.getSaasAttr());
        if (batchRequired && StringUtil.isEmpty(batch)) {
            throw new XbbException(ProductErrorCodeEnum.API_ERROR_205028, ProductErrorCodeEnum.API_ERROR_205028.getMsg() + ":" + productName);
        }
        if (!StringUtil.isEmpty(batch) && batch.length() > 100) {
            throw new XbbException(ProductErrorCodeEnum.API_ERROR_205020);
        }

        JSONObject redundantValueObject = (JSONObject) JSONObject.parse(redundantData);
        // 是否传了冗余数据
        boolean haveInfo = StringUtil.isNotEmpty(batch) || produceDate != 0 || guaranteePeriod != null || StringUtil.isNotEmpty(memo) || !redundantValueObject.isEmpty();
        if (Objects.equals(isProductStockInfo, 0)) {
            // baseInfo信息保存
            ProductBaseInfoEntity productBaseInfo = null;
            if (Objects.equals(operateType, OperateTypeEnum.NEW.getAlias())) {
                // 新建
                if (haveInfo) {
                    // 产品冗余信息
                    productBaseInfo = new ProductBaseInfoEntity();
                    productBaseInfo.setRefId(refId);
                    productBaseInfo.setRefType(refType);
                    productBaseInfo.setFormId(paasFormExplainEntity.getFormId());
                    productBaseInfo.setCorpid(corpid);
                    productBaseInfo.setBatch(batch);
                    productBaseInfo.setDel(0);
                    productBaseInfo.setProduceDate(produceDate);
                    productBaseInfo.setGuaranteePeriod(guaranteePeriod);
                    productBaseInfo.setMemo(memo);
                }
            } else if (Objects.equals(operateType, OperateTypeEnum.EDIT.getAlias())) {
                // 编辑
                // 更新产品关联冗余信息
                List<ProductBaseInfoEntity> productBaseInfoList = productBaseInfoModel.getByRefIdAndRefType(refId, refType, corpid);
                if (productBaseInfoList.size() > 0) {
                    productBaseInfo = productBaseInfoList.get(0);
                    productBaseInfo.setBatch(batch);
                    productBaseInfo.setProduceDate(produceDate);
                    productBaseInfo.setGuaranteePeriod(guaranteePeriod);
                    productBaseInfo.setMemo(memo);
                } else {
                    if (haveInfo) {
                        // 产品冗余信息
                        productBaseInfo = new ProductBaseInfoEntity();
                        productBaseInfo.setRefId(refId);
                        productBaseInfo.setRefType(refType);
                        productBaseInfo.setFormId(paasFormExplainEntity.getFormId());
                        productBaseInfo.setCorpid(corpid);
                        productBaseInfo.setBatch(batch);
                        productBaseInfo.setDel(0);
                        productBaseInfo.setProduceDate(produceDate);
                        productBaseInfo.setGuaranteePeriod(guaranteePeriod);
                        productBaseInfo.setMemo(memo);
                    }
                }
            }
            if (productBaseInfo == null) {
                // 前端没有传入库存相关信息，用户没有填写
                return;
            }
            if (redundantData != null) {
                JSONObject dataList = checkRedundantField4Save(explainList, redundantData);
                // 设置data属性的值
                productBaseInfo.setData(dataList);
            }
            productBaseInfoModel.save(productBaseInfo);
        } else if (Objects.equals(isProductStockInfo, 1)) {
            // stockInfo信息保存
            Long productId = 0L;
            Long warehouseId = 0L;
            Double productNum = 0D;
            Double cost = 0D;
            if (Objects.equals(XbbRefTypeEnum.OUTSTOCK_PRODUCT.getCode(), refType)) {
                OutstockProductEntity outstockProductEntity = productStockInfoSaveDTO.getOutstockProductEntity();
                productId = outstockProductEntity.getProductId();
                warehouseId = outstockProductEntity.getWarehouseId();
                productNum = outstockProductEntity.getProductNum();
                cost = outstockProductEntity.getCost();
            } else if (Objects.equals(XbbRefTypeEnum.INSTOCK_PRODUCT.getCode(), refType)) {
                InstockProductEntity instockProductEntity = productStockInfoSaveDTO.getInstockProductEntity();
                productId = instockProductEntity.getProductId();
                warehouseId = instockProductEntity.getWarehouseId();
                productNum = instockProductEntity.getProductNum();
                cost = instockProductEntity.getCost();
            }
            ProductStockInfoEntity productStockInfo = null;
            if (Objects.equals(operateType, OperateTypeEnum.NEW.getAlias())) {
                if (haveInfo) {
                    productStockInfo = new ProductStockInfoEntity();
                    productStockInfo.setCorpid(corpid);
                    productStockInfo.setFormId(paasFormExplainEntity.getFormId());
                    productStockInfo.setRefId(refId);
                    productStockInfo.setRefType(refType);
                    productStockInfo.setProductId(productId);
                    productStockInfo.setWarehouseId(warehouseId);
                    productStockInfo.setProductNum(productNum);
                    productStockInfo.setBatch(batch);
                    productStockInfo.setProduceDate(produceDate);
                    productStockInfo.setGuaranteePeriod(guaranteePeriod);
                    productStockInfo.setCost(cost);
                    productStockInfo.setMemo(memo);
                    productStockInfo.setDel(0);
                }
            } else if (Objects.equals(operateType, OperateTypeEnum.EDIT.getAlias())) {
                // 更新产品关联冗余信息
                List<ProductStockInfoEntity> productStockInfoList = productStockInfoModel.getByRefIdAndRefType(refId, refType, corpid);
                if (productStockInfoList.size() > 0) {
                    productStockInfo = productStockInfoList.get(0);
                    productStockInfo.setBatch(batch);
                    productStockInfo.setProduceDate(produceDate);
                    productStockInfo.setGuaranteePeriod(guaranteePeriod);
                    // TODO 小数精度
                    productStockInfo.setProductNum(productNum);
                    productStockInfo.setWarehouseId(warehouseId);
                    productStockInfo.setCost(cost);
                    productStockInfo.setMemo(memo);
                } else {
                    if (haveInfo) {
                        productStockInfo = new ProductStockInfoEntity();
                        productStockInfo.setCorpid(corpid);
                        productStockInfo.setFormId(paasFormExplainEntity.getFormId());
                        productStockInfo.setRefId(refId);
                        productStockInfo.setRefType(refType);
                        productStockInfo.setProductId(productId);
                        productStockInfo.setWarehouseId(warehouseId);
                        productStockInfo.setProductNum(productNum);
                        productStockInfo.setBatch(batch);
                        productStockInfo.setProduceDate(produceDate);
                        productStockInfo.setGuaranteePeriod(guaranteePeriod);
                        productStockInfo.setCost(cost);
                        productStockInfo.setMemo(memo);
                        productStockInfo.setDel(0);
                    }
                }
            }
            if (productStockInfo == null) {
                // 前端没有传入库存相关信息，用户没有填写
                return;
            }

            if (redundantData != null) {
                JSONObject dataList = checkRedundantField4Save(explainList, redundantData);
                // 设置data属性的值
                productStockInfo.setData(JSONObject.toJSONString(dataList));
            }
            productStockInfoModel.save(productStockInfo);
        }
    }

    @Override
    public JSONObject checkRedundantField4Save(List<FieldAttrEntity> explainList, String redundantData) throws XbbException{
        if(explainList == null || redundantData == null) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028);
        }
        // 判断redundantValues是否可用
        JSONObject redundantValueObject = null;
        try {
            redundantValueObject = (JSONObject) JSONObject.parse(redundantData);
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100015);
        }

        // 自定义字段解释集合
        Map<String, FieldAttrEntity> redundantExplainMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (FieldAttrEntity fieldAttrEntity : explainList) {
            if (Objects.equals(fieldAttrEntity.getIsRedundant(), 1)) {
                // 自定义字段
                String attr = fieldAttrEntity.getAttr();
                redundantExplainMap.put(attr, fieldAttrEntity);
            }
        }
        // 这里根据saasAttr进行对应匹配保存
        ValidateDataDTO validateDataDTO = new ValidateDataDTO();
        // 必填和数字校验等，只设置data和explainMap两个属性，别的属性这里用不到
        validateDataDTO.setData(redundantValueObject);
        validateDataDTO.setExplainMap(redundantExplainMap);
        formDataValidateDataHelp.validateData(validateDataDTO);

        return redundantValueObject;
    }

    @Override
    public ProductBaseInfoListVO findProductBaseInfoList(ProductBaseInfoListDTO productBaseInfoListDTO) throws XbbException {
        ProductBaseInfoListVO productBaseInfoListVO = new ProductBaseInfoListVO();
        try {
            Map<String, Object> param = BeanUtil.convertBean2Map(productBaseInfoListDTO, true);
            List<ProductBaseInfoEntity> productBaseInfoList = productBaseInfoModel.findEntitys(param);
            if (Objects.isNull(productBaseInfoList)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
            }
            productBaseInfoListVO.setProductBaseInfoList(productBaseInfoList);
        } catch (Exception e) {
            LOG.error("productBaseInfoServiceImpl.findProductBaseInfoList 获取产品冗余信息出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return productBaseInfoListVO;
    }

    @Override
    public ProductBaseInfoDeleteBatchVO deleteBatchByRefId(ProductBaseInfoDeleteBatchDTO productBaseInfoDeleteBatchDTO) throws XbbException {
        ProductBaseInfoDeleteBatchVO productBaseInfoDeleteBatchVO = new ProductBaseInfoDeleteBatchVO();
        try {
            List<Long> refIdIn = productBaseInfoDeleteBatchDTO.getRefIdList();
            String corpid = productBaseInfoDeleteBatchDTO.getCorpid();
            Integer refType = productBaseInfoDeleteBatchDTO.getRefType();
            if (!refIdIn.isEmpty()) {
                productBaseInfoModel.deleteByRefIds(corpid, refIdIn, refType);
            }
        } catch (Exception e) {
            LOG.error("productBaseInfoServiceImpl.findProductBaseInfoList 获取产品冗余信息出错：", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, SystemErrorCodeEnum.API_ERROR_100001.getMsg());
        }
        return productBaseInfoDeleteBatchVO;
    }

    @Override
    public void updateWithoutId(List<ProductBaseInfoEntity> updateProductBaseInfoList, int refType, String corpid) {
        if (updateProductBaseInfoList.isEmpty()){
            return;
        }
        List<Long> refIdList = new ArrayList<>();
        Map<Long,ProductBaseInfoEntity> updateMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        updateProductBaseInfoList.forEach(item ->{
            refIdList.add(item.getRefId());
            updateMap.put(item.getRefId(),item);
        });
        List<ProductBaseInfoEntity> productBaseInfoEntityList = productBaseInfoModel.getProductBaseInfoList(corpid,refType,refIdList);
        if (productBaseInfoEntityList.isEmpty()){
            return;
        }
//        List<ProductBaseInfoEntity> updateList = new ArrayList<>();
        for (ProductBaseInfoEntity entity : productBaseInfoEntityList){
            if (updateMap.containsKey(entity.getRefId())){
                ProductBaseInfoEntity updateEntity = updateMap.get(entity.getRefId());
                updateEntity.setId(entity.getId());
//                updateList.add(updateEntity);
                productBaseInfoModel.update(updateEntity);
            }
        }
//        if (!updateList.isEmpty()){
//            productBaseInfoModel.updateBatch();
//        }
    }
}
